package nl.haemers.data.serializers 
{
	import flash.utils.Dictionary;
	import nl.haemers.data.constants.DataTypes;
	import nl.haemers.data.reflection.IMethod;
	import nl.haemers.data.reflection.IProperty;
	import nl.haemers.data.reflection.Type;
	import nl.haemers.utils.Logger;
	/**
	 * @author Jonathan Haemers
	 */
	public class BaseSerializer implements ISerializer
	{
		/**
		 * The baseparser has all the base methods for parsing an inputobject(JSON/XML) to a VO.
		 * 
		 */
		private var _debug:Boolean;
		
		private var _dirtyList:Dictionary;
		 
		public function BaseSerializer(debug:Boolean = true) 
		{
			this.debug = debug;
			_dirtyList = new Dictionary();
		}
		
		/** Public methods **/
		
		/** Getters & Setters **/
		public function get debug() : Boolean
		{
			return _debug;
		}
		public function set debug(value:Boolean) : void 
		{
			_debug = value;
		}
		
		/** Protected methods **/
		/**
		 * Method to write a value to an object(VO). We also keep track of an parsinglist this way we have control over
		 * the items which we don't want to overwrite. 
		 * @param	refObject
		 * @param	name
		 * @param	value
		 * @return
		 */
		protected function writeValueToProperty(refObject:Object, property:IProperty, value:Object, type:Type = null) : Object
		{
			if (_dirtyList[property] == null || _dirtyList[property] != refObject)
			{
				refObject[property.propertyName] = value;
				if(!property.overwriteable)
					_dirtyList[property] = refObject;
			}
			else
			{
				Logger.w("Property: " + property.propertyName + " is already set by the parser skip this one.");
			}
			
			return refObject;
		}
		/**
		 * This method could throw Errors! So always use a try catch around this Method
		 * @param	refObject
		 * @param	method
		 * @param	args
		 * @return
		 */
		protected function writeValueToMethod(refObject:Object, method:IMethod, args:Array) : Object
		{
			if (_dirtyList[method] == null || _dirtyList[method] != refObject)
			{
				refObject[method.methodName].apply(refObject, args);
				if(!method.overwriteable)
					_dirtyList[method] = refObject;
			}
			else
			{
				Logger.w("Method: " + method.methodName+ " is already set by the parser skip this one.");
			}
			
			
			return refObject;
		}
		
		protected function parseValue(value:String, type:String) : *
		{
			if (value == null || type == null || type == DataTypes.BOOLEAN)
			{
				Logger.i(value + " : " + type);
			}
			
			switch(type)
			{
				case DataTypes.ARRAY:
					//not sure we need this
					return new Array();
				case DataTypes.BOOLEAN:
					//it's a boolean
					return (value == "true");
				case DataTypes.INT:
					return parseInt(value);
				case DataTypes.NUMBER:
					if (value == null)
					{
						return NaN;
					}	
					value = value.replace(/,/g, ".");
					return parseFloat(value);
				case DataTypes.STRING:
					return value;
				case DataTypes.UINT:
					return parseInt(value);
				case DataTypes.VECTOR:
					//not sure we need this
					break;
				default:
					//return null when we couldn't parse the value
					return null;
			}
		}
		
		/** Private methods **/
	}

}